{
 "cells": [
  {
   "cell_type": "code",
   "metadata": {
    "collapsed": true,
    "ExecuteTime": {
     "end_time": "2025-01-22T07:57:44.805919Z",
     "start_time": "2025-01-22T07:57:42.482440Z"
    }
   },
   "source": [
    "import os\n",
    "\n",
    "from sklearn.datasets import fetch_california_housing\n",
    "from sklearn.linear_model import LinearRegression, SGDRegressor, Ridge, LogisticRegression, Lasso\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.preprocessing import StandardScaler\n",
    "from sklearn.metrics import mean_squared_error, classification_report, roc_auc_score\n",
    "import joblib\n",
    "import pandas as pd\n",
    "import numpy as np"
   ],
   "outputs": [],
   "execution_count": 1
  },
  {
   "metadata": {},
   "cell_type": "code",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "获取特征值\n",
      "(20640, 8)\n",
      "--------------------------------------------------\n",
      "[   8.3252       41.            6.98412698    1.02380952  322.\n",
      "    2.55555556   37.88       -122.23      ]\n",
      "目标值\n",
      "[4.526 3.585 3.521 ... 0.923 0.847 0.894]\n",
      ".. _california_housing_dataset:\n",
      "\n",
      "California Housing dataset\n",
      "--------------------------\n",
      "\n",
      "**Data Set Characteristics:**\n",
      "\n",
      ":Number of Instances: 20640\n",
      "\n",
      ":Number of Attributes: 8 numeric, predictive attributes and the target\n",
      "\n",
      ":Attribute Information:\n",
      "    - MedInc        median income in block group\n",
      "    - HouseAge      median house age in block group\n",
      "    - AveRooms      average number of rooms per household\n",
      "    - AveBedrms     average number of bedrooms per household\n",
      "    - Population    block group population\n",
      "    - AveOccup      average number of household members\n",
      "    - Latitude      block group latitude\n",
      "    - Longitude     block group longitude\n",
      "\n",
      ":Missing Attribute Values: None\n",
      "\n",
      "This dataset was obtained from the StatLib repository.\n",
      "https://www.dcc.fc.up.pt/~ltorgo/Regression/cal_housing.html\n",
      "\n",
      "The target variable is the median house value for California districts,\n",
      "expressed in hundreds of thousands of dollars ($100,000).\n",
      "\n",
      "This dataset was derived from the 1990 U.S. census, using one row per census\n",
      "block group. A block group is the smallest geographical unit for which the U.S.\n",
      "Census Bureau publishes sample data (a block group typically has a population\n",
      "of 600 to 3,000 people).\n",
      "\n",
      "A household is a group of people residing within a home. Since the average\n",
      "number of rooms and bedrooms in this dataset are provided per household, these\n",
      "columns may take surprisingly large values for block groups with few households\n",
      "and many empty houses, such as vacation resorts.\n",
      "\n",
      "It can be downloaded/loaded using the\n",
      ":func:`sklearn.datasets.fetch_california_housing` function.\n",
      "\n",
      ".. rubric:: References\n",
      "\n",
      "- Pace, R. Kelley and Ronald Barry, Sparse Spatial Autoregressions,\n",
      "  Statistics and Probability Letters, 33 (1997) 291-297\n",
      "\n",
      "--------------------------------------------------\n",
      "['MedInc', 'HouseAge', 'AveRooms', 'AveBedrms', 'Population', 'AveOccup', 'Latitude', 'Longitude']\n"
     ]
    }
   ],
   "execution_count": 2,
   "source": [
    "\"\"\"\n",
    "线性回归直接预测房子价格\n",
    ":return: None\n",
    "\"\"\"\n",
    "# 获取数据\n",
    "fe_cal = fetch_california_housing(data_home='data')\n",
    "\n",
    "print(\"获取特征值\")\n",
    "print(fe_cal.data.shape)\n",
    "print('-' * 50)\n",
    "print(fe_cal.data[0])\n",
    "print(\"目标值\")\n",
    "print(fe_cal.target) # 单位是10万美金\n",
    "print(fe_cal.DESCR)\n",
    "print('-' * 50)\n",
    "print(fe_cal.feature_names) #特征列的名字"
   ]
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "MedInc - 中位收入（Median Income）\n",
    "\n",
    "HouseAge - 房屋年龄（House Age）\n",
    "\n",
    "AveRooms - 平均房间数（Average Number of Rooms）\n",
    "\n",
    "AveBedrms - 平均卧室数（Average Number of Bedrooms）\n",
    "\n",
    "Population - 人口数量（Population）\n",
    "\n",
    "AveOccup - 平均居住人数（Average Occupancy）\n",
    "\n",
    "Latitude - 纬度（Latitude）\n",
    "\n",
    "Longitude - 经度（Longitude）\n"
   ]
  },
  {
   "metadata": {},
   "cell_type": "code",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(20640,)"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 9,
   "source": "fe_cal.target.shape"
  },
  {
   "metadata": {},
   "cell_type": "code",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(15480, 8)\n",
      "(15480,)\n"
     ]
    }
   ],
   "execution_count": 57,
   "source": [
    "# 分割数据集到训练集和测试集\n",
    "x_train, x_test, y_train, y_test = train_test_split(fe_cal.data, fe_cal.target, test_size=0.25, random_state=1)\n",
    "print(x_train.shape)\n",
    "\n",
    "# 进行标准化处理(?) 目标值处理？\n",
    "# 特征值和目标值是都必须进行标准化处理, 实例化两个标准化API\n",
    "std_x = StandardScaler()\n",
    "\n",
    "x_train = std_x.fit_transform(x_train) # 训练集标准化\n",
    "x_test = std_x.transform(x_test) # 测试集a标准化\n",
    "print(y_train.shape) # 1维"
   ]
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## 对目标值进行标准化处理"
  },
  {
   "metadata": {},
   "cell_type": "code",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(15480, 1)\n"
     ]
    }
   ],
   "execution_count": 55,
   "source": [
    "# 目标值进行了标准化\n",
    "std_y = StandardScaler()\n",
    "\n",
    "# 标签进行标准化\n",
    "# 目标值是一维的，这里需要传进去2维的\n",
    "y_train = std_y.fit_transform(y_train.reshape(-1, 1))\n",
    "y_test = std_y.transform(y_test.reshape(-1, 1))\n",
    "print(y_train.shape)"
   ]
  },
  {
   "metadata": {},
   "cell_type": "code",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(3,)\n",
      "(3, 1)\n"
     ]
    }
   ],
   "execution_count": 42,
   "source": [
    "# reshape例子\n",
    "test1=np.array([1,2,3])\n",
    "print(test1.shape)\n",
    "print(test1.reshape(-1,1).shape)  # 变2维，-1会自动计算这一维的大小，以确保重塑后的数组总大小不变。"
   ]
  },
  {
   "metadata": {},
   "cell_type": "code",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "回归系数 [[ 0.71942632  0.10518431 -0.23147194  0.26802332 -0.00448136 -0.03495117\n",
      "  -0.7849086  -0.76307353]]\n",
      "正规方程测试集里面每个房子的预测价格： [[2.12391852]\n",
      " [0.93825754]\n",
      " [2.7088455 ]\n",
      " [1.70873764]\n",
      " [2.82954754]\n",
      " [3.50376456]\n",
      " [3.0147162 ]\n",
      " [1.62781292]\n",
      " [1.74317518]\n",
      " [2.01897806]]\n",
      "正规方程的均方误差： 0.5356532845422556\n"
     ]
    }
   ],
   "execution_count": 44,
   "source": [
    "import os\n",
    "# estimator预测\n",
    "# 正规方程求解方式预测结果，正规方程进行线性回归\n",
    "lr = LinearRegression()\n",
    "# fit是耗时的\n",
    "lr.fit(x_train, y_train)\n",
    "#回归系数可以看特征与目标之间的相关性\n",
    "print('回归系数', lr.coef_)\n",
    "\n",
    "# 标准化后的房价\n",
    "y_predict = lr.predict(x_test)\n",
    "\n",
    "# 预测测试集的房子价格，通过inverse得到真正的房子价格（标准化的逆运算）\n",
    "\n",
    "# 保存训练好的模型，模型中保存的是w的值，也保存了模型结构\n",
    "# 保存模型放在fit之后即可\n",
    "os.unlink('./tmp/test.pkl') # 删除之前的模型文件\n",
    "joblib.dump(lr, \"./tmp/test.pkl\")\n",
    "print(\"正规方程测试集里面每个房子的预测价格：\", y_predict[0:10])\n",
    "#下面是求测试集的损失，用均方误差，公式是(y_test-y_predict)^2/n\n",
    "print(\"正规方程的均方误差：\", mean_squared_error(y_test, y_predict))"
   ]
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## 未对目标值进行标准化处理"
  },
  {
   "metadata": {},
   "cell_type": "code",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "回归系数 [ 0.83167028  0.12159502 -0.26758589  0.30983997 -0.00518054 -0.04040421\n",
      " -0.90736902 -0.88212727]\n",
      "正规方程测试集里面每个房子的预测价格： [2.12391852 0.93825754 2.7088455  1.70873764 2.82954754 3.50376456\n",
      " 3.0147162  1.62781292 1.74317518 2.01897806]\n",
      "正规方程的均方误差： 0.5356532845422556\n"
     ]
    }
   ],
   "execution_count": 58,
   "source": [
    "lr = LinearRegression()\n",
    "# fit是耗时的\n",
    "lr.fit(x_train, y_train)\n",
    "#回归系数可以看特征与目标之间的相关性\n",
    "print('回归系数', lr.coef_)\n",
    "y_predict = lr.predict(x_test)\n",
    "\n",
    "# 保存训练好的模型，模型中保存的是w的值，也保存了模型结构\n",
    "# 保存模型放在fit之后即可\n",
    "os.unlink('./tmp/test.pkl') # 删除之前的模型文件\n",
    "joblib.dump(lr, \"./tmp/test.pkl\")\n",
    "print(\"正规方程测试集里面每个房子的预测价格：\", y_predict[0:10])\n",
    "#下面是求测试集的损失，用均方误差，公式是(y_test-y_predict)^2/n\n",
    "print(\"正规方程的均方误差：\", mean_squared_error(y_test, y_predict))"
   ]
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# 2 加载保存的模型"
  },
  {
   "metadata": {},
   "cell_type": "code",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "保存的模型预测的结果： [[2.12391852]\n",
      " [0.93825754]\n",
      " [2.7088455 ]\n",
      " [1.70873764]\n",
      " [2.82954754]\n",
      " [3.50376456]\n",
      " [3.0147162 ]\n",
      " [1.62781292]\n",
      " [1.74317518]\n",
      " [2.01897806]]\n",
      "正规方程inverse后的均方误差： 0.5356532845422556\n"
     ]
    }
   ],
   "execution_count": 45,
   "source": [
    "#模拟上线时加载模型\n",
    "model = joblib.load(\"./tmp/test.pkl\")\n",
    "# # 因为目标值进行了标准化，一定要把预测后的值逆向转换回来\n",
    "y_predict = model.predict(x_test)\n",
    "\n",
    "\n",
    "# print(\"保存的模型预测的结果：\", y_predict[0:10])\n",
    "# print(\"正规方程的均方误差：\", mean_squared_error(y_test, y_predict))\n",
    "print(\"保存的模型预测的结果：\",std_y.inverse_transform(y_predict)[0:10])\n",
    "print(\"正规方程inverse后的均方误差：\", mean_squared_error(y_test,std_y.inverse_transform(y_predict)))"
   ]
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "###### 手算均方误差"
  },
  {
   "metadata": {},
   "cell_type": "code",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.375"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 46,
   "source": [
    "y_true = [3, -0.5, 2, 7]\n",
    "y_pred = [2.5, 0.0, 2, 8]\n",
    "mean_squared_error(y_true, y_pred)"
   ]
  },
  {
   "metadata": {},
   "cell_type": "code",
   "outputs": [
    {
     "data": {
      "text/plain": "0.375"
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 20,
   "source": [
    "#人工求均方误差\n",
    "(np.square(3 - 2.5) + np.square(0.5) + 1) / 4\n"
   ]
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "# 3 线性回归之梯度下降去进行房价预测\n",
    "- 学习率\n",
    "2.L1 与 L2 的区别？\n",
    "- L1正则化产生稀疏的权值, L2正则化产生平滑的权值， \n",
    "- L1正则化偏向于稀疏，它会自动进行特征选择，去掉一些没用的特征，也就是将这些特征对应的权重置为0. \n",
    "- L2主要功能是为了防止过拟合，当要求参数越小时，说明模型越简单，而模型越简单则，越趋向于平滑，从而防止过拟合。\n",
    "\n",
    "正则化力度： \n",
    "- 大： 参数趋近于0\n",
    "- 小： 参数变化小（高阶项权重没变）\n"
   ]
  },
  {
   "metadata": {},
   "cell_type": "code",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "梯度下降的回归系数 [ 0.84109028  0.12594282 -0.2234344   0.30798368  0.00769904 -0.00396853\n",
      " -0.92019263 -0.88634833]\n",
      "梯度下降的均方误差： 0.5393083592982708\n"
     ]
    }
   ],
   "execution_count": 49,
   "source": [
    "# 梯度下降去进行房价预测,数据量大要用这个\n",
    "# learning_rate的不同方式，代表学习率变化的算法不一样,比如constant,invscaling,adaptive\n",
    "# 默认可以去调 eta0 = 0.008，会改变learning_rate的初始值\n",
    "# learning_rate='optimal',alpha是正则化力度，但是会影响学习率的值，由alpha来算学习率\n",
    "# penalty代表正则化，分为l1和l2\n",
    "# max_iter是最大迭代次数\n",
    "sgd = SGDRegressor(eta0=0.01,penalty='l2', max_iter=1000)\n",
    "# 训练\n",
    "sgd.fit(x_train, y_train)\n",
    "#\n",
    "print('梯度下降的回归系数', sgd.coef_)\n",
    "\n",
    "# 预测测试集的房子价格\n",
    "# y_sgd_predict = std_y.inverse_transform(sgd.predict(x_test).reshape(-1, 1))\n",
    "y_predict = sgd.predict(x_test)\n",
    "# print(\"梯度下降测试集里面每个房子的预测价格：\", y_sgd_predict)\n",
    "print(\"梯度下降的均方误差：\", mean_squared_error(y_test, y_predict))\n",
    "# print(\"梯度下降的原始房价量纲均方误差：\", mean_squared_error(std_y.inverse_transform(y_test), y_sgd_predict))"
   ]
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "###  手写简单SGD算法"
  },
  {
   "metadata": {},
   "cell_type": "code",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "w 0.29999999999999993 损失3.0799999999999996\n",
      "w -0.12 损失1.6688\n",
      "w -0.372 损失1.160768\n",
      "w -0.5232 损失0.9778764800000002\n",
      "w -0.61392 损失0.9120355328\n",
      "w -0.6683520000000001 损失0.888332791808\n",
      "w -0.7010112000000001 损失0.87979980505088\n",
      "w -0.72060672 损失0.8767279298183168\n",
      "w -0.732364032 损失0.8756220547345941\n",
      "w -0.7394184192 损失0.8752239397044537\n",
      "w -0.74365105152 损失0.8750806182936035\n",
      "w -0.746190630912 损失0.8750290225856971\n",
      "w -0.7477143785472 损失0.8750104481308509\n",
      "w -0.74862862712832 损失0.8750037613271064\n",
      "w -0.749177176276992 损失0.8750013540777584\n",
      "w -0.7495063057661951 损失0.8750004874679931\n",
      "w -0.7497037834597171 损失0.8750001754884773\n",
      "w -0.7498222700758302 损失0.8750000631758519\n",
      "w -0.7498933620454982 损失0.8750000227433066\n",
      "w -0.7499360172272989 损失0.8750000081875902\n",
      "w -0.7499616103363793 损失0.8750000029475327\n",
      "w -0.7499769662018276 损失0.8750000010611116\n",
      "w -0.7499861797210966 损失0.8750000003820002\n",
      "w -0.749991707832658 损失0.87500000013752\n",
      "w -0.7499950246995948 损失0.8750000000495071\n",
      "w -0.7499970148197569 损失0.8750000000178226\n",
      "w -0.7499982088918541 损失0.8750000000064162\n",
      "w -0.7499989253351125 损失0.8750000000023095\n",
      "w -0.7499993552010675 损失0.8750000000008316\n",
      "w -0.7499996131206406 损失0.8750000000002991\n"
     ]
    }
   ],
   "execution_count": 52,
   "source": [
    "w=1\n",
    "learning_rate=0.1\n",
    "def loss(w):\n",
    "    return 2*w**2+3*w+2\n",
    "def dao_shu(w):\n",
    "    return 4*w+3\n",
    "for i in range(30):\n",
    "    w=w-learning_rate*dao_shu(w)\n",
    "    print(f'w {w} 损失{loss(w)}')"
   ]
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# 4 岭回归"
  },
  {
   "metadata": {},
   "cell_type": "code",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 0.83166963  0.12159681 -0.26758236  0.30983534 -0.00517992 -0.04040432\n",
      " -0.90735215 -0.88211025]\n",
      "(5160,)\n",
      "岭回归的均方误差： 0.5356531179270398\n"
     ]
    }
   ],
   "execution_count": 53,
   "source": [
    "# 岭回归去进行房价预测\n",
    "#岭回归是对线性回归加入L2正则化，L2正则化是对系数的平方和进行惩罚\n",
    "#alpha就是补偿的系数\n",
    "#正规方程求解，加补偿就可以让正规方程可逆\n",
    "rd = Ridge(alpha=0.02)\n",
    "\n",
    "rd.fit(x_train, y_train)\n",
    "\n",
    "print(rd.coef_)\n",
    "#\n",
    "# # 预测测试集的房子价格\n",
    "print(rd.predict(x_test).shape)\n",
    "# y_rd_predict = std_y.inverse_transform(rd.predict(x_test))\n",
    "y_predict = rd.predict(x_test)\n",
    "# print(\"岭回归里面每个房子的预测价格：\", y_rd_predict)\n",
    "\n",
    "print(\"岭回归的均方误差：\", mean_squared_error(y_test, y_predict))\n",
    "# print(\"岭回归的均方误差：\", mean_squared_error(std_y.inverse_transform(y_test), y_rd_predict))"
   ]
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# 5 Lasso回归去进行房价预测"
  },
  {
   "metadata": {},
   "cell_type": "code",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(15480, 8)\n",
      "(15480,)\n",
      "[ 0.82655827  0.1225482  -0.25369194  0.29596304 -0.00381001 -0.03948424\n",
      " -0.89646842 -0.87060253]\n",
      "(5160,)\n",
      "--------------------------------------------------\n",
      "Lasso回归的均方误差： 0.5356324125105497\n"
     ]
    }
   ],
   "execution_count": 54,
   "source": [
    "#alpha就是补偿的系数\n",
    "print(x_train.shape)\n",
    "print(y_train.shape)\n",
    "ls = Lasso(alpha=0.001)\n",
    "\n",
    "ls.fit(x_train, y_train)\n",
    "\n",
    "print(ls.coef_)\n",
    "#\n",
    "# # 预测测试集的房子价格\n",
    "print(ls.predict(x_test).shape)\n",
    "print('-'*50)\n",
    "# y_ls_predict = std_y.inverse_transform(ls.predict(x_test).reshape(-1,1))\n",
    "y_predict = ls.predict(x_test)\n",
    "# print(\"Lasso回归里面每个房子的预测价格：\", y_rd_predict)\n",
    "#\n",
    "print(\"Lasso回归的均方误差：\", mean_squared_error(y_test, y_predict))\n",
    "# print(\"Lasso回归的均方误差：\", mean_squared_error(std_y.inverse_transform(y_test), y_ls_predict))"
   ]
  },
  {
   "cell_type": "markdown",
   "source": [
    "# 6 逻辑回归（解决分类问题）\n",
    "- sigmoid函数: why?——要保证可导，若直接让>0为1，<0为0，则阶跃函数不可导+对数似然损失比均分损失区分度更大"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "source": [
    "np.log(0.5)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-01-22T13:10:10.502497Z",
     "start_time": "2025-01-22T13:10:10.495943Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "np.float64(-0.6931471805599453)"
      ]
     },
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 59
  },
  {
   "cell_type": "code",
   "source": [
    "np.log(0.3)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-01-22T13:10:12.149383Z",
     "start_time": "2025-01-22T13:10:12.145336Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "np.float64(-1.2039728043259361)"
      ]
     },
     "execution_count": 60,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 60
  },
  {
   "cell_type": "code",
   "source": [
    "x=np.arange(0.001,1,0.01) #0-1之间，步长0.01\n",
    "import matplotlib.pyplot as plt\n",
    "plt.plot(x,-np.log(x))  #以e为底部\n",
    "plt.show()"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    },
    "ExecuteTime": {
     "end_time": "2025-01-22T13:10:36.875176Z",
     "start_time": "2025-01-22T13:10:36.103637Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ],
      "image/png": "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"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 61
  },
  {
   "cell_type": "code",
   "source": [
    "x=np.arange(0,1,0.01)\n",
    "import matplotlib.pyplot as plt\n",
    "plt.plot(x,-np.log(1-x))\n",
    "plt.show()"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    },
    "ExecuteTime": {
     "end_time": "2025-01-22T13:12:34.793178Z",
     "start_time": "2025-01-22T13:12:34.743434Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ],
      "image/png": "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PDzc+POf/2xs27bNuOmmm4zExESjsrKyx/f/61//MkJCQoxHHnnE2L59u/Gzn/3MCAsLM7Zs2eL1sdtNb6/1NddcYzz11FPGxo0bjR07dhg33HCDkZCQYBw8eNDrY/f3a+22d+9eY+DAgcbMmTONuXPnem28gXStW1pajMmTJxsXX3yxsWrVKn3NV6xYYRQWFnp97P5+rV988UUjIiJC36vrvGzZMiMzM9O44447vD52u1myZIlx7733Gq+//ro64WksXrz4K9+/Z88eIzo62rjzzjv1Z+OTTz6pPyuXLl1q2phsEyzOPPNMY8GCBV3PnU6nkZWVZSxcuLDH91999dXGJZdc0u21qVOnGv/5n//p8bHaXW+v9fHa29uNuLg4469//asHRxm411pd3+nTpxt/+tOfjPnz5xMsPHStn3nmGSMvL89obW314igD81qr986aNavba+qDb8aMGR4fqz+R0wgWP/nJT4zRo0d3e23evHnGnDlzTBuHLZZCWltbZf369XqK/dieI+r56tWre/wa9fqx71fmzJlz0vej79f6eEeOHJG2tjZJTk724EgD91r/8pe/lPT0dPne977npZEG5rV+6623ZNq0aXopZMCAATJmzBj59a9/LU6n04sjD4xrPX36dP017uWSPXv26CWniy++2GvjDhSrvfDZ6PUmZH1RU1Oj/2NW/3EfSz3fuXNnj19TUVHR4/vV6zD3Wh/vrrvu0ut9x//wov/XetWqVfL8889LYWGhl0YZuNdafbh99NFHcu211+oPueLiYvnRj36kQ7OqYgjzrvU111yjv+7ss8/WHTTb29vlBz/4gfz0pz/10qgDR8VJPhtVB9SjR4/qPS79ZYsZC9jHww8/rDcVLl68WG/agnlUu+LrrrtOb5ZNTU319XD8nsvl0jNDf/zjH2XSpEkyb948uffee+XZZ5/19dD8jtpMqGaDnn76admwYYO8/vrr8u6778qDDz7o66HBX2cs1C/RkJAQqays7Pa6ep6RkdHj16jXe/N+9P1auz322GM6WHz44Ycybtw4D4808K51SUmJ7Nu3T+8AP/bDTwkNDZWioiLJz8/3wsgD4+danQQJCwvTX+c2cuRI/X98aro/PDzc4+MOlGv985//XIfm73//+/q5OsXX1NQkN998sw5zaikF5jjZZ6Nqp27GbIVii39b6j9g9X8My5cv7/YLVT1Xa6A9Ua8f+37lgw8+OOn70fdrrTzyyCP6/y6WLl0qkydP9tJoA+taq6PTW7Zs0csg7tvll18u5513nn6sjujBvJ/rGTNm6OUPd3hTdu3apQMHocLca632ZR0fHtyBjnZW5vLKZ6Nho+NL6jjSCy+8oI/I3Hzzzfr4UkVFhf7z6667zrj77ru7HTcNDQ01HnvsMX0E8v777+e4qYeu9cMPP6yPlr322mtGeXl5183hcPjwn8I/r/XxOBXiuWt94MABfbrplltuMYqKiox33nnHSE9PN371q1/58J/CP6+1+v2srvXLL7+sj0O+//77Rn5+vj7dh6+mfs+qo/7qpj7SH3/8cf14//79+s/VdVbX+/jjpj/+8Y/1Z6MqFRCwx00Vdd42NzdXf4ip40xr1qzp+rNzzz1X/5I91j//+U+joKBAv18dr3n33Xd9MGp76s21HjRokP6BPv6mflnA/J/rYxEsPHutP/vsM31MXX1IqqOnDz30kD7uC3OvdVtbm/GLX/xCh4nIyEgjJyfH+NGPfmTU1dX5aPT28fHHH/f4+9d9fdW9ut7Hf82ECRP0vxv1c/2Xv/zF1DHRNh0AAJjGFnssAACAPRAsAACAaQgWAADANAQLAABgGoIFAAAwDcECAACYhmABAABMQ7AAAACmIVgAAADTECwAAIBpCBYAAMA0BAsAACBm+f/rCbw+zK0MQgAAAABJRU5ErkJggg=="
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 62
  },
  {
   "cell_type": "code",
   "source": [
    "\"\"\"\n",
    "逻辑回归做二分类进行癌症预测（根据细胞的属性特征）\n",
    ":return: NOne\n",
    "\"\"\"\n",
    "# 构造列标签名字\n",
    "column = ['Sample code number', 'Clump Thickness', 'Uniformity of Cell Size', 'Uniformity of Cell Shape',\n",
    "          'Marginal Adhesion', 'Single Epithelial Cell Size', 'Bare Nuclei', 'Bland Chromatin', 'Normal Nucleoli',\n",
    "          'Mitoses', 'Class']\n",
    "\n",
    "# 读取数据\n",
    "# data = pd.read_csv(\n",
    "#     \"https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/breast-cancer-wisconsin.data\",\n",
    "#     names=column)\n",
    "data = pd.read_csv(\n",
    "    \"./data/breast-cancer-wisconsin.csv\",\n",
    "    names=column)\n",
    "# print(data) #想看可以解除\n",
    "#当你读取数据时，看上去是数值的列，读进来是字符串，说明里边\n",
    "# 存在了非数值情况\n",
    "print(data.info())  # 如Bare Nuclei有很多是？，但把它当成字符串读出，所以非空\n",
    "print('-' * 50)\n",
    "data.describe(include='all')"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    },
    "ExecuteTime": {
     "end_time": "2025-01-22T13:27:02.365519Z",
     "start_time": "2025-01-22T13:27:02.324281Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "RangeIndex: 699 entries, 0 to 698\n",
      "Data columns (total 11 columns):\n",
      " #   Column                       Non-Null Count  Dtype \n",
      "---  ------                       --------------  ----- \n",
      " 0   Sample code number           699 non-null    int64 \n",
      " 1   Clump Thickness              699 non-null    int64 \n",
      " 2   Uniformity of Cell Size      699 non-null    int64 \n",
      " 3   Uniformity of Cell Shape     699 non-null    int64 \n",
      " 4   Marginal Adhesion            699 non-null    int64 \n",
      " 5   Single Epithelial Cell Size  699 non-null    int64 \n",
      " 6   Bare Nuclei                  699 non-null    object\n",
      " 7   Bland Chromatin              699 non-null    int64 \n",
      " 8   Normal Nucleoli              699 non-null    int64 \n",
      " 9   Mitoses                      699 non-null    int64 \n",
      " 10  Class                        699 non-null    int64 \n",
      "dtypes: int64(10), object(1)\n",
      "memory usage: 60.2+ KB\n",
      "None\n",
      "--------------------------------------------------\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "        Sample code number  Clump Thickness  Uniformity of Cell Size  \\\n",
       "count         6.990000e+02       699.000000               699.000000   \n",
       "unique                 NaN              NaN                      NaN   \n",
       "top                    NaN              NaN                      NaN   \n",
       "freq                   NaN              NaN                      NaN   \n",
       "mean          1.071704e+06         4.417740                 3.134478   \n",
       "std           6.170957e+05         2.815741                 3.051459   \n",
       "min           6.163400e+04         1.000000                 1.000000   \n",
       "25%           8.706885e+05         2.000000                 1.000000   \n",
       "50%           1.171710e+06         4.000000                 1.000000   \n",
       "75%           1.238298e+06         6.000000                 5.000000   \n",
       "max           1.345435e+07        10.000000                10.000000   \n",
       "\n",
       "        Uniformity of Cell Shape  Marginal Adhesion  \\\n",
       "count                 699.000000         699.000000   \n",
       "unique                       NaN                NaN   \n",
       "top                          NaN                NaN   \n",
       "freq                         NaN                NaN   \n",
       "mean                    3.207439           2.806867   \n",
       "std                     2.971913           2.855379   \n",
       "min                     1.000000           1.000000   \n",
       "25%                     1.000000           1.000000   \n",
       "50%                     1.000000           1.000000   \n",
       "75%                     5.000000           4.000000   \n",
       "max                    10.000000          10.000000   \n",
       "\n",
       "        Single Epithelial Cell Size Bare Nuclei  Bland Chromatin  \\\n",
       "count                    699.000000         699       699.000000   \n",
       "unique                          NaN          11              NaN   \n",
       "top                             NaN           1              NaN   \n",
       "freq                            NaN         402              NaN   \n",
       "mean                       3.216023         NaN         3.437768   \n",
       "std                        2.214300         NaN         2.438364   \n",
       "min                        1.000000         NaN         1.000000   \n",
       "25%                        2.000000         NaN         2.000000   \n",
       "50%                        2.000000         NaN         3.000000   \n",
       "75%                        4.000000         NaN         5.000000   \n",
       "max                       10.000000         NaN        10.000000   \n",
       "\n",
       "        Normal Nucleoli     Mitoses       Class  \n",
       "count        699.000000  699.000000  699.000000  \n",
       "unique              NaN         NaN         NaN  \n",
       "top                 NaN         NaN         NaN  \n",
       "freq                NaN         NaN         NaN  \n",
       "mean           2.866953    1.589413    2.689557  \n",
       "std            3.053634    1.715078    0.951273  \n",
       "min            1.000000    1.000000    2.000000  \n",
       "25%            1.000000    1.000000    2.000000  \n",
       "50%            1.000000    1.000000    2.000000  \n",
       "75%            4.000000    1.000000    4.000000  \n",
       "max           10.000000   10.000000    4.000000  "
      ],
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Sample code number</th>\n",
       "      <th>Clump Thickness</th>\n",
       "      <th>Uniformity of Cell Size</th>\n",
       "      <th>Uniformity of Cell Shape</th>\n",
       "      <th>Marginal Adhesion</th>\n",
       "      <th>Single Epithelial Cell Size</th>\n",
       "      <th>Bare Nuclei</th>\n",
       "      <th>Bland Chromatin</th>\n",
       "      <th>Normal Nucleoli</th>\n",
       "      <th>Mitoses</th>\n",
       "      <th>Class</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>count</th>\n",
       "      <td>6.990000e+02</td>\n",
       "      <td>699.000000</td>\n",
       "      <td>699.000000</td>\n",
       "      <td>699.000000</td>\n",
       "      <td>699.000000</td>\n",
       "      <td>699.000000</td>\n",
       "      <td>699</td>\n",
       "      <td>699.000000</td>\n",
       "      <td>699.000000</td>\n",
       "      <td>699.000000</td>\n",
       "      <td>699.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>unique</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>11</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>top</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>1</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>freq</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>402</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>mean</th>\n",
       "      <td>1.071704e+06</td>\n",
       "      <td>4.417740</td>\n",
       "      <td>3.134478</td>\n",
       "      <td>3.207439</td>\n",
       "      <td>2.806867</td>\n",
       "      <td>3.216023</td>\n",
       "      <td>NaN</td>\n",
       "      <td>3.437768</td>\n",
       "      <td>2.866953</td>\n",
       "      <td>1.589413</td>\n",
       "      <td>2.689557</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>std</th>\n",
       "      <td>6.170957e+05</td>\n",
       "      <td>2.815741</td>\n",
       "      <td>3.051459</td>\n",
       "      <td>2.971913</td>\n",
       "      <td>2.855379</td>\n",
       "      <td>2.214300</td>\n",
       "      <td>NaN</td>\n",
       "      <td>2.438364</td>\n",
       "      <td>3.053634</td>\n",
       "      <td>1.715078</td>\n",
       "      <td>0.951273</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>min</th>\n",
       "      <td>6.163400e+04</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>NaN</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>2.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>25%</th>\n",
       "      <td>8.706885e+05</td>\n",
       "      <td>2.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>2.000000</td>\n",
       "      <td>NaN</td>\n",
       "      <td>2.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>2.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>50%</th>\n",
       "      <td>1.171710e+06</td>\n",
       "      <td>4.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>2.000000</td>\n",
       "      <td>NaN</td>\n",
       "      <td>3.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>2.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>75%</th>\n",
       "      <td>1.238298e+06</td>\n",
       "      <td>6.000000</td>\n",
       "      <td>5.000000</td>\n",
       "      <td>5.000000</td>\n",
       "      <td>4.000000</td>\n",
       "      <td>4.000000</td>\n",
       "      <td>NaN</td>\n",
       "      <td>5.000000</td>\n",
       "      <td>4.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>4.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>max</th>\n",
       "      <td>1.345435e+07</td>\n",
       "      <td>10.000000</td>\n",
       "      <td>10.000000</td>\n",
       "      <td>10.000000</td>\n",
       "      <td>10.000000</td>\n",
       "      <td>10.000000</td>\n",
       "      <td>NaN</td>\n",
       "      <td>10.000000</td>\n",
       "      <td>10.000000</td>\n",
       "      <td>10.000000</td>\n",
       "      <td>4.000000</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ]
     },
     "execution_count": 65,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 65
  },
  {
   "cell_type": "code",
   "source": [
    "data['Bare Nuclei'].unique() #因为上面发现它是object类型"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    },
    "ExecuteTime": {
     "end_time": "2025-01-22T13:32:41.968426Z",
     "start_time": "2025-01-22T13:32:41.964485Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array(['1', '10', '2', '4', '3', '9', '7', '?', '5', '8', '6'],\n",
       "      dtype=object)"
      ]
     },
     "execution_count": 66,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 66
  },
  {
   "cell_type": "code",
   "source": [
    "# 缺失值进行处理\n",
    "data = data.replace(to_replace='?', value=np.nan)\n",
    "# 直接删除，哪一行有空值，就删除对应的样本\n",
    "data = data.dropna()\n",
    "print('-' * 50)\n",
    "print(data.shape)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    },
    "ExecuteTime": {
     "end_time": "2025-01-22T14:08:04.977601Z",
     "start_time": "2025-01-22T14:08:04.968969Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "--------------------------------------------------\n",
      "(683, 11)\n"
     ]
    }
   ],
   "execution_count": 77
  },
  {
   "cell_type": "code",
   "source": [
    "data.info()"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    },
    "ExecuteTime": {
     "end_time": "2025-01-22T13:48:17.920246Z",
     "start_time": "2025-01-22T13:48:17.905122Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "RangeIndex: 699 entries, 0 to 698\n",
      "Data columns (total 11 columns):\n",
      " #   Column                       Non-Null Count  Dtype \n",
      "---  ------                       --------------  ----- \n",
      " 0   Sample code number           699 non-null    int64 \n",
      " 1   Clump Thickness              699 non-null    int64 \n",
      " 2   Uniformity of Cell Size      699 non-null    int64 \n",
      " 3   Uniformity of Cell Shape     699 non-null    int64 \n",
      " 4   Marginal Adhesion            699 non-null    int64 \n",
      " 5   Single Epithelial Cell Size  699 non-null    int64 \n",
      " 6   Bare Nuclei                  699 non-null    object\n",
      " 7   Bland Chromatin              699 non-null    int64 \n",
      " 8   Normal Nucleoli              699 non-null    int64 \n",
      " 9   Mitoses                      699 non-null    int64 \n",
      " 10  Class                        699 non-null    int64 \n",
      "dtypes: int64(10), object(1)\n",
      "memory usage: 60.2+ KB\n"
     ]
    }
   ],
   "execution_count": 67
  },
  {
   "cell_type": "code",
   "source": "print(column[10])",
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    },
    "ExecuteTime": {
     "end_time": "2025-01-22T13:50:58.671531Z",
     "start_time": "2025-01-22T13:50:58.666906Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Class\n"
     ]
    }
   ],
   "execution_count": 73
  },
  {
   "cell_type": "code",
   "source": [
    "# 分类的类别是2和4,对应 \"良性\", \"恶性\"\n",
    "data[column[10]].unique()"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    },
    "ExecuteTime": {
     "end_time": "2025-01-22T13:48:27.271611Z",
     "start_time": "2025-01-22T13:48:27.265433Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([2, 4])"
      ]
     },
     "execution_count": 70,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 70
  },
  {
   "cell_type": "code",
   "source": [
    "data.info()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-01-22T14:07:46.944243Z",
     "start_time": "2025-01-22T14:07:46.936948Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "RangeIndex: 699 entries, 0 to 698\n",
      "Data columns (total 11 columns):\n",
      " #   Column                       Non-Null Count  Dtype \n",
      "---  ------                       --------------  ----- \n",
      " 0   Sample code number           699 non-null    int64 \n",
      " 1   Clump Thickness              699 non-null    int64 \n",
      " 2   Uniformity of Cell Size      699 non-null    int64 \n",
      " 3   Uniformity of Cell Shape     699 non-null    int64 \n",
      " 4   Marginal Adhesion            699 non-null    int64 \n",
      " 5   Single Epithelial Cell Size  699 non-null    int64 \n",
      " 6   Bare Nuclei                  699 non-null    object\n",
      " 7   Bland Chromatin              699 non-null    int64 \n",
      " 8   Normal Nucleoli              699 non-null    int64 \n",
      " 9   Mitoses                      699 non-null    int64 \n",
      " 10  Class                        699 non-null    int64 \n",
      "dtypes: int64(10), object(1)\n",
      "memory usage: 60.2+ KB\n"
     ]
    }
   ],
   "execution_count": 74
  },
  {
   "cell_type": "code",
   "source": [
    "column[6]"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-01-22T14:07:49.415022Z",
     "start_time": "2025-01-22T14:07:49.409946Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Bare Nuclei'"
      ]
     },
     "execution_count": 75,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 75
  },
  {
   "cell_type": "code",
   "source": [
    "# 把第6列的字符串转化为数字类型\n",
    "data[column[6]] = data[column[6]].astype('int16')"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-01-22T14:08:13.195070Z",
     "start_time": "2025-01-22T14:08:13.191355Z"
    }
   },
   "outputs": [],
   "execution_count": 78
  },
  {
   "cell_type": "code",
   "source": [
    "data.info()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-01-22T14:08:47.035003Z",
     "start_time": "2025-01-22T14:08:47.029368Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "Index: 683 entries, 0 to 698\n",
      "Data columns (total 11 columns):\n",
      " #   Column                       Non-Null Count  Dtype\n",
      "---  ------                       --------------  -----\n",
      " 0   Sample code number           683 non-null    int64\n",
      " 1   Clump Thickness              683 non-null    int64\n",
      " 2   Uniformity of Cell Size      683 non-null    int64\n",
      " 3   Uniformity of Cell Shape     683 non-null    int64\n",
      " 4   Marginal Adhesion            683 non-null    int64\n",
      " 5   Single Epithelial Cell Size  683 non-null    int64\n",
      " 6   Bare Nuclei                  683 non-null    int16\n",
      " 7   Bland Chromatin              683 non-null    int64\n",
      " 8   Normal Nucleoli              683 non-null    int64\n",
      " 9   Mitoses                      683 non-null    int64\n",
      " 10  Class                        683 non-null    int64\n",
      "dtypes: int16(1), int64(10)\n",
      "memory usage: 60.0 KB\n"
     ]
    }
   ],
   "execution_count": 79
  },
  {
   "cell_type": "code",
   "source": [
    "# 进行数据的分割,第0列是编号，不可以作为特征，把第1-9列作为特征，第10列作为标签\n",
    "x_train, x_test, y_train, y_test = train_test_split(data[column[1:10]], data[column[10]], test_size=0.25,\n",
    "                                                    random_state=1)\n",
    "\n",
    "# 进行标准化处理\n",
    "std = StandardScaler()\n",
    "\n",
    "x_train = std.fit_transform(x_train) # 训练集标准化\n",
    "x_test = std.transform(x_test) # 测试集标准化\n",
    "x_train[0]"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    },
    "ExecuteTime": {
     "end_time": "2025-01-22T14:09:52.939207Z",
     "start_time": "2025-01-22T14:09:52.918216Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([-1.21629973, -0.70863282, -0.75174943,  0.04301674, -0.55657068,\n",
       "       -0.71054972, -0.99312055, -0.62911518, -0.36280962])"
      ]
     },
     "execution_count": 80,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 80
  },
  {
   "cell_type": "code",
   "source": [
    "# 逻辑回归预测\n",
    "# C正则化力度，跟学习率有关\n",
    "# solver = 'liblinear'  solver是学习率优化算法，就是学习率会随着epoch的变化而变化\n",
    "# epoch就代表第几次迭代\n",
    "# max_iter 最大迭代次数\n",
    "lg = LogisticRegression(C=0.5, solver='lbfgs')\n",
    "lg.fit(x_train, y_train)\n",
    "\n",
    "# 逻辑回归的权重参数，了解，没那么重要\n",
    "print(lg.coef_)\n",
    "\n",
    "y_predict = lg.predict(x_test)\n",
    "print(y_predict) # 预测的标签\n",
    "\n",
    "print(\"准确率：\", lg.score(x_test, y_test))\n",
    "print(y_test[0:5])\n",
    "print('-'*50)\n",
    "\n",
    "print(lg.predict_proba(x_test)[0:5])  #得出对应分类的概率"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    },
    "ExecuteTime": {
     "end_time": "2025-01-22T14:18:37.616507Z",
     "start_time": "2025-01-22T14:18:37.607839Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1.11400191 0.25293086 0.78938469 0.60986034 0.0728013  1.10834397\n",
      "  0.7794668  0.64312128 0.67692658]]\n",
      "[2 2 2 4 2 4 2 2 4 4 2 2 4 2 2 4 2 2 2 2 2 2 2 4 4 2 2 2 4 4 2 2 4 4 2 4 2\n",
      " 2 4 4 4 2 2 4 2 2 2 2 4 2 2 2 4 2 2 2 4 2 2 2 2 4 2 2 2 4 2 4 4 2 2 4 2 2\n",
      " 4 2 2 2 2 2 2 2 4 2 4 4 2 2 2 4 2 2 4 2 2 4 4 2 2 4 2 2 4 4 2 2 2 2 4 2 4\n",
      " 4 2 4 2 4 2 2 2 2 4 2 4 2 2 2 2 2 4 2 2 2 2 2 2 2 4 2 4 4 2 2 4 2 2 2 2 4\n",
      " 2 2 2 2 2 4 2 4 2 4 2 2 4 2 4 2 4 4 2 4 2 2 2]\n",
      "准确率： 0.9824561403508771\n",
      "444    2\n",
      "24     2\n",
      "195    2\n",
      "49     4\n",
      "375    2\n",
      "Name: Class, dtype: int64\n",
      "--------------------------------------------------\n",
      "[[0.94893919 0.05106081]\n",
      " [0.99494175 0.00505825]\n",
      " [0.98365149 0.01634851]\n",
      " [0.02707911 0.97292089]\n",
      " [0.99732446 0.00267554]]\n"
     ]
    }
   ],
   "execution_count": 84
  },
  {
   "cell_type": "code",
   "source": [
    "# 为什么还要看下召回率，labels和target_names对应\n",
    "# macro avg 平均值  weighted avg 加权平均值\n",
    "print(classification_report(y_test, y_predict, labels=[2, 4], target_names=[\"良性\", \"恶性\"]))\n",
    "# AUC计算要求是二分类，不需要是0和1\n",
    "print(\"AUC指标：\", roc_auc_score(y_test, y_predict))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-01-22T14:16:14.698412Z",
     "start_time": "2025-01-22T14:16:14.685807Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "              precision    recall  f1-score   support\n",
      "\n",
      "          良性       0.97      1.00      0.99       111\n",
      "          恶性       1.00      0.95      0.97        60\n",
      "\n",
      "    accuracy                           0.98       171\n",
      "   macro avg       0.99      0.97      0.98       171\n",
      "weighted avg       0.98      0.98      0.98       171\n",
      "\n",
      "AUC指标： 0.975\n"
     ]
    }
   ],
   "execution_count": 82
  },
  {
   "cell_type": "code",
   "source": [
    "print(x_train.shape)\n",
    "print(x_test.shape)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    },
    "ExecuteTime": {
     "end_time": "2025-01-22T14:28:56.992203Z",
     "start_time": "2025-01-22T14:28:56.988202Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(512, 9)\n",
      "(171, 9)\n"
     ]
    }
   ],
   "execution_count": 85
  },
  {
   "cell_type": "code",
   "source": [
    "print(-np.log(0.1))"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    },
    "ExecuteTime": {
     "end_time": "2025-01-22T14:29:01.969657Z",
     "start_time": "2025-01-22T14:29:01.965557Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2.3025850929940455\n"
     ]
    }
   ],
   "execution_count": 86
  },
  {
   "cell_type": "code",
   "source": "-np.log(0.9)",
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    },
    "ExecuteTime": {
     "end_time": "2025-01-22T14:29:02.345640Z",
     "start_time": "2025-01-22T14:29:02.342069Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "np.float64(0.10536051565782628)"
      ]
     },
     "execution_count": 87,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 87
  },
  {
   "cell_type": "code",
   "source": [
    "x=-3/10\n",
    "y=5*x**2+3*x+4\n",
    "y"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    },
    "ExecuteTime": {
     "end_time": "2025-01-22T14:29:03.133491Z",
     "start_time": "2025-01-22T14:29:03.129548Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3.55"
      ]
     },
     "execution_count": 88,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 88
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "#### 生成模型（要先验概率）和判别模型"
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
